home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / debug / Common / SegmentManager.m < prev   
Text File  |  1994-11-29  |  12KB  |  513 lines

  1. #import "SegmentManager.h"
  2. #import <stdlib.h>
  3. #import <string.h>
  4. #import <mach-o/loader.h>
  5. #import <sys/types.h>
  6. #import <sys/stat.h>
  7. #import <mach-o/ldsyms.h>
  8. #import <libc.h>
  9. #import <objc/maptable.h>
  10. #import <mach-o/fat.h>
  11.  
  12. #define REALLY_SWAP_LONG(a) ( ((a) << 24) | \
  13.               (((a) << 8) & 0x00ff0000) | \
  14.               (((a) >> 8) & 0x0000ff00) | \
  15.     ((unsigned long)(a) >> 24) )
  16.  
  17. #define SWAP_LONG(a) (shouldSwap ? REALLY_SWAP_LONG(a) : (a))
  18.  
  19. @implementation SegmentManager
  20.  
  21. static NXMapTable *managers = NULL;
  22.  
  23. +initialize
  24. {
  25.     static BOOL beenHere = NO;
  26.     
  27.     if (!beenHere) {
  28.     beenHere = YES;
  29.     managers = NXCreateMapTable(NXStrValueMapPrototype, 0);
  30.     }
  31.     return self;
  32. }
  33.  
  34. -init
  35. {
  36.     relocSize = sizeof(Segment);
  37.     rmFlags.shouldSortRelocs = YES;
  38.     [self readInAllRelocs];
  39.     lastReloc = NULL;
  40.     if (numRelocs) {
  41.     if (images[0].name)
  42.         NXMapInsert(managers, images[0].name, self);
  43.     return self;
  44.     } else {
  45.     [self free];
  46.     return nil;
  47.     }
  48. }
  49.  
  50. -(void)setCpuType: (cpu_type_t)type
  51. {
  52.     static cpu_type_t defaultCpuType = 0;
  53.     if (type)
  54.     cpuType = type;
  55.     else {
  56.     if (!defaultCpuType) {
  57.         struct host_basic_info host_basic_info;
  58.         unsigned int count = HOST_BASIC_INFO_COUNT;
  59.         
  60.         if (host_info(host_self(), HOST_BASIC_INFO,
  61.               (host_info_t)(&host_basic_info),
  62.               &count) == KERN_SUCCESS)
  63.         defaultCpuType = host_basic_info.cpu_type;
  64.     }
  65.     cpuType = defaultCpuType;
  66.     }
  67. }
  68.  
  69. -initFile: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type
  70. {
  71.     SegmentManager *oldManager;
  72.     if (oldManager = NXMapGet(managers, theName)) {
  73.     close(desc);
  74.     [self free];
  75.     return oldManager;
  76.     } else  {
  77.     name = malloc(strlen(theName) + 1);
  78.     strcpy(name, theName);
  79.     skipShlibs = shouldSkipShlibs;
  80.     imageFd = desc;
  81.     [self setCpuType: type];
  82.     [self getImages];
  83.     return [self init];
  84.     }
  85. }
  86.  
  87. static const char loadedName[] = "loaded file";
  88.  
  89. -(struct mach_header *)headerFromStart: (void *)start
  90. {
  91.     struct mach_header *header = start;
  92.     if (header->magic == MH_MAGIC && header->cputype == cpuType)
  93.     return header;
  94.     else {
  95.     struct fat_header *fatHeader = start;
  96.     if ((fatHeader->magic == FAT_MAGIC)
  97.         || (fatHeader->magic == REALLY_SWAP_LONG(FAT_MAGIC))) {
  98.         BOOL shouldSwap = !(fatHeader->magic == FAT_MAGIC);
  99.         unsigned int nArches;
  100.         struct fat_arch *fatArch, *foundArch;
  101.         
  102.         for (nArches = SWAP_LONG(fatHeader->nfat_arch),
  103.          fatArch = (struct fat_arch *)(fatHeader + 1),
  104.          foundArch = NULL;
  105.          nArches && !foundArch;
  106.          fatArch++, nArches--) {
  107.         if (cpuType == SWAP_LONG(fatArch->cputype))
  108.             foundArch = fatArch;
  109.         }
  110.         if (foundArch)
  111.         return start + SWAP_LONG(foundArch->offset);
  112.         else
  113.         return NULL;
  114.     } else
  115.         return NULL;
  116.     }
  117. }
  118.  
  119. -initHeader: (struct mach_header *)header withSize: (int)size
  120. {
  121.     numImages = 1;
  122.     [self setCpuType: 0];
  123.     images = malloc(sizeof(*images));
  124.     images->header = [self headerFromStart: header];
  125.     images->size = size;
  126.     images->name = NULL;
  127.     images->mtime = 0;
  128.     name = malloc(sizeof(loadedName));
  129.     strcpy(name, loadedName);
  130.     return [self init];
  131. }
  132.  
  133. -initFile: (STR)theName
  134. {
  135.     return [self initFile: theName skipShlibs: NO withDesc: -1 cpuType: 0];
  136. }
  137.  
  138. +newExecutable: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type
  139. {
  140.     SegmentManager *sm = [[super alloc] initFile: (STR)theName
  141.                                     skipShlibs: shouldSkipShlibs
  142.                       withDesc: desc
  143.                    cpuType: type];
  144.     if (sm && [sm isExecutable])
  145.      return sm;
  146.     else {
  147.     [sm free];
  148.     return nil;
  149.     }
  150. }
  151.  
  152. +newExecutable: (STR)theName
  153. {
  154.     return [self newExecutable: theName skipShlibs: NO withDesc: -1 cpuType: 0];
  155. }
  156.  
  157. +newCore: (STR)theName
  158. {
  159.     SegmentManager *sm = [[super alloc] initFile: (STR)theName];
  160.     if (sm && [sm isCore])
  161.      return sm;
  162.     else {
  163.     [sm free];
  164.     return nil;
  165.     }
  166. }
  167.  
  168. +newFile: (STR)theName
  169. {
  170.     return [[super alloc] initFile: (STR)theName];
  171. }
  172.  
  173. +newShlib: (STR)theName cpuType: (cpu_type_t)type
  174. {
  175.     SegmentManager *sm = [[super alloc] initFile: (STR)theName
  176.                                     skipShlibs: YES
  177.                       withDesc: -1
  178.                        cpuType: type];
  179.     if (sm && [sm isShlib])
  180.      return sm;
  181.     else {
  182.     [sm free];
  183.     return nil;
  184.     }
  185. }
  186.  
  187. +newShlib: (STR)theName
  188. {
  189.     return [self newShlib: theName cpuType: 0];
  190. }
  191.  
  192. +newHeader: (struct mach_header *)header withSize: (int)size
  193. {
  194.     return [[super alloc] initHeader: header withSize: size];
  195. }
  196.  
  197. -(STR)executableName
  198. {
  199.     return name;
  200. }
  201.  
  202. -(long)mtime
  203. {
  204.     return images[0].mtime;
  205. }
  206.  
  207. -free
  208. {
  209.     NXMapRemove(managers, name);
  210.     free(name); name = NULL;
  211.     return [super free];
  212. }
  213.  
  214. -invalidate
  215. {
  216.     int count;
  217.     Image *image;
  218.     
  219.     if (images) {
  220.     for (count = numImages, image = images; count; count--, image++) {
  221.         if (image->deallocate)
  222.         vm_deallocate(task_self(),
  223.                 (vm_address_t)image->header,
  224.                 image->size);
  225.     }
  226.     free(images); images = NULL;
  227.     numImages = 0;
  228.     }
  229.     return [super invalidate];
  230. }
  231.  
  232. -(void)getImages
  233. {
  234.     struct stat imageStat;
  235.     struct load_command *loadCmd;
  236.     struct fvmlib_command *fvmCmd;
  237.     struct mach_header *header;
  238.     int i;
  239.     Image *image;
  240.     numImages = 0;
  241.     if (imageFd < 0)
  242.     imageFd = open(name, O_RDONLY, 0);
  243.     if (imageFd >= 0) {
  244.     fstat(imageFd, &imageStat);
  245.     if (map_fd(imageFd,
  246.            0,
  247.            (vm_address_t *)&header,
  248.            YES,
  249.            imageStat.st_size) == 0) {
  250. //        printf("Map_fp successfull.\n");
  251.         header = [self headerFromStart: header];
  252.         if (header) {
  253. //            printf("Got header.\n");
  254.         numImages = 1;
  255.         if (skipShlibs) {
  256.             images = malloc(sizeof(Image));
  257.             images->name = name;
  258.             images->header = header;
  259.             images->size = imageStat.st_size;
  260.             images->deallocate = YES;
  261.             images->mtime = imageStat.st_mtime;
  262.         } else {
  263.             for (i = 0, loadCmd = (struct load_command *)(header + 1);
  264.              i < header->ncmds;
  265.              i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  266.             if (loadCmd->cmd == LC_LOADFVMLIB) 
  267.                 numImages++;
  268.             }
  269.             image
  270.             = images
  271.             = calloc(numImages, sizeof(Image));
  272.             image->name = name;
  273.             image->header = header;
  274.             image->size = imageStat.st_size;
  275.             image->deallocate = YES;
  276.             image->mtime = imageStat.st_mtime;
  277.             image++;
  278.             for (i = 0, loadCmd = (struct load_command *)(header + 1);
  279.              i < header->ncmds;
  280.              i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  281.             int shlibFd;
  282.             if (loadCmd->cmd == LC_LOADFVMLIB) {
  283.                 fvmCmd = (struct fvmlib_command *)loadCmd;
  284.                 image->name
  285.                 = (void *)fvmCmd + fvmCmd->fvmlib.name.offset;
  286.                 shlibFd = open(image->name, O_RDONLY, 0);
  287.                 if (shlibFd >= 0) {
  288.                 fstat(shlibFd, &imageStat);
  289.                 image->size = imageStat.st_size;
  290.                 image->mtime = imageStat.st_mtime;
  291.                 if (map_fd(shlibFd,
  292.                        0,
  293.                        (vm_address_t *)&image->header,
  294.                        YES,
  295.                        image->size)
  296.                       == 0) {
  297.                         image->header
  298.                     = [self headerFromStart: image->header];
  299.                     image->deallocate = YES;
  300.                     image++;
  301.                 } else
  302.                     numImages--;
  303.                 close(shlibFd);
  304.                 } else
  305.                 numImages--;
  306.             }
  307.             }
  308.         }
  309.         } else {
  310.         return;
  311.         }
  312.     } else {
  313.         extern int errno;
  314. //        printf("Map_fd failed, errno = %d.\n", errno);
  315.     }
  316.     close(imageFd);
  317.     imageFd = -1;
  318.     }
  319. }
  320.                             
  321. -(int)numSegments
  322. {
  323.     int count, numSegs = 0, i;
  324.     Image *image;
  325.     struct load_command *loadCmd;
  326.     struct mach_header *header;
  327.     for (count = numImages,
  328.      image = images;
  329.      count;
  330.      count--, image++) {
  331.     header = image->header;
  332.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  333.          i < header->ncmds;
  334.          i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  335.         if (loadCmd->cmd == LC_SEGMENT) 
  336.         numSegs++;
  337.     }
  338.     }
  339.     return numSegs;
  340. }
  341.  
  342. -(BOOL)validate
  343. {
  344.     int nImages, i;
  345.     Image *image;
  346.     struct mach_header *header;
  347.     struct load_command *loadCmd;
  348.     struct segment_command *segCmd;
  349.     BOOL allOK = YES;
  350.     for (nImages = numImages,
  351.      image = images;
  352.      allOK && nImages;
  353.      nImages--, image++) {
  354.     header = image->header;
  355.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  356.          allOK && i < header->ncmds;
  357.          i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  358.         if (loadCmd->cmd == LC_SEGMENT) {
  359.         segCmd = (struct segment_command *)loadCmd;
  360.         if ((segCmd->fileoff + segCmd->vmsize) > image->size)
  361.             allOK = NO;
  362.         }
  363.         if (!loadCmd->cmdsize)
  364.         allOK = NO;
  365.     }
  366.     }
  367.     return allOK;
  368. }
  369.  
  370. -(void)readInSegments
  371. {
  372.     int nImages, i;
  373.     Image *image;
  374.     struct mach_header *header;
  375.     struct load_command *loadCmd;
  376.     struct segment_command *segCmd;
  377.     Segment *segment = relocs;
  378.     for (nImages = numImages,
  379.      image = images;
  380.      nImages;
  381.      nImages--, image++) {
  382.     header = image->header;
  383.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  384.          i < header->ncmds;
  385.          i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  386.         if (loadCmd->cmd == LC_SEGMENT) {
  387.         segCmd = (struct segment_command *)loadCmd;
  388.         segment->address = segCmd->vmaddr;
  389.         segment->size = segCmd->vmsize;
  390.         segment->data = (vm_address_t)header + segCmd->fileoff;
  391.         segment->maxAddress = segment->address + segment->size;
  392.         segment->displacement = segment->data - segment->address;
  393.         segment->maxData = segment->data + segment->size;
  394.         segment->segName = segCmd->segname;
  395.         segment->rFlags.readIn = YES;
  396.         ((void *)segment) += relocSize;
  397.         }
  398.     }
  399.     }
  400. }
  401.  
  402. -(void)_readInAllRelocs
  403. {
  404.     numRelocs = [self numSegments];
  405.     relocs = calloc(numRelocs, relocSize);
  406.     [self readInSegments];
  407.     rmFlags.invalid = NO;
  408. }
  409.  
  410. -(struct mach_header *)getMachHeader
  411. {
  412.     if (numImages)
  413.     return images[0].header;
  414.     else
  415.     return NULL;
  416. }
  417.  
  418. -(int)getNumMachHeaders
  419. {
  420.     return numImages;
  421. }
  422.  
  423. -(struct mach_header **)getMachHeaders
  424. {
  425.     struct mach_header **headers;
  426.     int headerIndex;
  427.     headers = malloc((numImages + 1) * sizeof(*headers));
  428.     for (headerIndex = 0; headerIndex < numImages; headerIndex++)
  429.     headers[headerIndex] = images[headerIndex].header;
  430.     headers[numImages] = NULL;
  431.     return headers;
  432. }
  433.  
  434. -(struct mach_header **)getMachHeadersWithNames: (char ***)names
  435. {
  436.     struct mach_header **headers;
  437.     char **theNames;
  438.     int headerIndex;
  439.     headers = malloc((numImages + 1) * sizeof(*headers));
  440.     *names = theNames = malloc((numImages + 1) * sizeof(*theNames));
  441.     for (headerIndex = 0; headerIndex < numImages; headerIndex++) {
  442.     headers[headerIndex] = images[headerIndex].header;
  443.     theNames[headerIndex] = images[headerIndex].name;
  444.     }
  445.     headers[numImages] = NULL;
  446.     theNames[numImages] = NULL;
  447.     return headers;
  448. }
  449.  
  450. -(struct load_command *)findLoadCommand: (unsigned long)command
  451.                               forHeader: (struct mach_header *)header
  452. {
  453.     int i;
  454.     struct load_command *loadCmd, *foundCmd = NULL;
  455.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  456.      i < header->ncmds && !foundCmd;
  457.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  458.     if (loadCmd->cmd == command)
  459.         foundCmd = loadCmd;
  460.     }
  461.     return foundCmd;
  462. }
  463.  
  464. -(int)numCommands: (unsigned long)command
  465.         forHeader: (struct mach_header *)header
  466. {
  467.     int i, nCommands = 0;
  468.     struct load_command *loadCmd;
  469.     for (i = 0, loadCmd = (struct load_command *)(header + 1);
  470.      i < header->ncmds;
  471.      i++, ((void *)loadCmd) += loadCmd->cmdsize) {
  472.     if (loadCmd->cmd == command)
  473.         nCommands++;
  474.     }
  475.     return nCommands;
  476. }
  477.  
  478. -(struct symtab_command *)symCmd
  479. {
  480.     return (struct symtab_command *)
  481.              [self findLoadCommand: LC_SYMTAB
  482.                      forHeader: images[0].header];
  483. }
  484.  
  485. -(char *)stringTable
  486. {
  487.     struct symtab_command *symCmd = [self symCmd];
  488.     return (char *)(images[0].header) + symCmd->stroff;
  489. }
  490.  
  491. -(BOOL)isCore
  492. {
  493.     return images && images[0].header->filetype == MH_CORE;
  494. }
  495.  
  496. -(BOOL)isShlib
  497. {
  498.     return images && images[0].header->filetype == MH_FVMLIB;
  499. }
  500.  
  501. -(BOOL)isExecutable
  502. {
  503.     BOOL ret = images && ((images[0].header->filetype == MH_EXECUTE)
  504.               || (images[0].header->filetype == MH_OBJECT)
  505.                       || (images[0].header->filetype == MH_PRELOAD));
  506. //    if (ret)
  507. //    printf("Is executable.\n");
  508. //    else
  509. //    printf("Isn't executable.\n");
  510.     return ret;
  511. }
  512.  
  513. @end